package cn.feizhu.aimarket.ai.workflow.service;

import cn.feizhu.aimarket.ai.workflow.event.BookSavedEvent;
import cn.feizhu.aimarket.model.domain.Book;
import cn.feizhu.aimarket.service.BookService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 工作流数据存储服务
 * 统一处理工作流中的数据存储操作，包括书籍、用户消息等
 *
 * @author feizhu
 * @since 2025/10/21
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class WorkflowDataService {

    private final BookService bookService;
    private final ApplicationEventPublisher eventPublisher;
    // 后续可以添加其他Service，如UserMessageService

    /**
     * 保存书籍信息
     * 暂时未添加重试
     *
     * @param appId 应用ID
     * @param userId 用户ID
     * @param title 书籍标题
     * @param filePath 文件路径
     * @param description 描述（可选）
     * @return 保存的书籍ID
     */
    @Transactional(rollbackFor = Exception.class)
    public Long saveBook(Long appId, Long userId, String title, String filePath, String description) {
        try {
            log.info("开始保存书籍 - appId: {}, userId: {}, title: {}", appId, userId, title);

            Book book = new Book();
            book.setAppId(appId);
            book.setUserId(userId);
            book.setTitle(title);
            book.setUri(filePath);
            book.setDescription(description);

            boolean saved = bookService.save(book);
            if (!saved) {
                throw new RuntimeException("书籍保存失败");
            }

            log.info("书籍保存成功 - bookId: {}", book.getId());

            // 发布书籍保存事件，用于后续处理（如通知、统计等）
            eventPublisher.publishEvent(new BookSavedEvent(this, book.getId(), userId, appId, title, filePath));

            return book.getId();

        } catch (Exception e) {
            log.error("保存书籍失败 - appId: {}, userId: {}, title: {}", appId, userId, title, e);
            throw new RuntimeException("保存书籍失败: " + e.getMessage(), e);
        }
    }

    /**
     * 保存用户消息（预留接口）
     * 支持重试机制，最多重试3次，每次间隔1秒
     *
     * @param userId 用户ID
     * @param appId 应用ID
     * @param message 消息内容
     * @param messageType 消息类型
     * @return 消息ID
     */
    @Retryable(
        retryFor = {Exception.class},
        maxAttempts = 3,
        backoff = @Backoff(delay = 1000, multiplier = 2)
    )
    @Transactional(rollbackFor = Exception.class)
    public Long saveUserMessage(Long userId, Long appId, String message, String messageType) {
        try {
            log.info("开始保存用户消息 - userId: {}, appId: {}, messageType: {}", userId, appId, messageType);

            // TODO: 实现用户消息保存逻辑
            // UserMessage userMessage = new UserMessage();
            // userMessage.setUserId(userId);
            // userMessage.setAppId(appId);
            // userMessage.setMessage(message);
            // userMessage.setMessageType(messageType);
            // userMessageService.save(userMessage);

            log.info("用户消息保存成功");
            return 1L; // 临时返回值

        } catch (Exception e) {
            log.error("保存用户消息失败 - userId: {}, appId: {}", userId, appId, e);
            throw new RuntimeException("保存用户消息失败: " + e.getMessage(), e);
        }
    }

    /**
     * 批量保存数据（用于需要原子性操作的场景）
     *
     * @param appId 应用ID
     * @param userId 用户ID
     * @param bookTitle 书籍标题
     * @param bookFilePath 书籍文件路径
     * @param userMessage 用户消息
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveBatch(Long appId, Long userId, String bookTitle, String bookFilePath, String userMessage) {
        try {
            log.info("开始批量保存数据 - appId: {}, userId: {}", appId, userId);

            // 保存书籍
            saveBook(appId, userId, bookTitle, bookFilePath, null);

            // 保存用户消息
            if (userMessage != null && !userMessage.trim().isEmpty()) {
                saveUserMessage(userId, appId, userMessage, "WORKFLOW_INPUT");
            }

            log.info("批量保存数据完成");

        } catch (Exception e) {
            log.error("批量保存数据失败 - appId: {}, userId: {}", appId, userId, e);
            throw new RuntimeException("批量保存数据失败: " + e.getMessage(), e);
        }
    }
}
